package com.yc.nfc;

import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;

/**
 * @author benjaminwan
 */
public abstract class SerialHelper {
    private SerialPort mSerialPort;
    private OutputStream mOutputStream;
    private InputStream mInputStream;
    private ReadThread mReadThread;
    private SendThread mSendThread;
    private String sPort = "/dev/s3c2410_serial0";
    private int iBaudRate = 9600;
    private boolean _isOpen = false;
    private byte[] _bLoopData = new byte[]{0x30};
    private int iDelay = 500;

    //----------------------------------------------------
    public SerialHelper(String sPort, int iBaudRate) {
        this.sPort = sPort;
        this.iBaudRate = iBaudRate;
    }
    public SerialHelper(int com) {
        this("/dev/ttyS"+com, 115200);
    }
    public SerialHelper() {
        this("/dev/ttyS3", 115200);
    }

    public SerialHelper(String sPort) {
        this(sPort, 9600);
    }

    public SerialHelper(String sPort, String sBaudRate) {
        this(sPort, Integer.parseInt(sBaudRate));
    }

    //----------------------------------------------------
    public void open() throws SecurityException, IOException, InvalidParameterException {
        mSerialPort = new SerialPort(new File(sPort), iBaudRate, 0);
        mOutputStream = mSerialPort.getOutputStream();

        mInputStream = mSerialPort.getInputStream();
        //设置扇区密钥
//        doSetParamTatol();
//        doSetParam();
//        doReadParm();
        //发送读卡指令
     /*   mSendThread = new SendThread();
        mSendThread.start();*/

        mReadThread = new ReadThread();
        mReadThread.start();
        _isOpen = true;
    }

    public  void doReadParm() {
        byte[] btArray = new byte[7];//3
        btArray[0] = (byte) 0x5A;//5A
        btArray[1] = (byte) 0xAA;//AA
        btArray[2] = (byte) 0x00;//0x38 长度35
        btArray[3] = (byte) 0x04;//0x03 命令字

        btArray[4] = (byte) 0xFB;//0x03 命令字
        btArray[5] = (byte) 0x6B;//6B 包尾
        btArray[6] = (byte) 0xBB;//BB
        send(btArray);
    }

    //----------------------------------------------------
    public void close() {
        if (mReadThread != null)
            mReadThread.interrupt();
        if (mSerialPort != null) {
            mSerialPort.close();
            mSerialPort = null;
        }
        _isOpen = false;
    }

    //----------------------------------------------------
    public void send(byte[] bOutArray) {
        try {
            mOutputStream.write(bOutArray);
            Log.d("T1", "发送数据");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //----------------------------------------------------
    public void sendHex(String sHex) {
        byte[] bOutArray = MyFunc.HexToByteArr(sHex);
        send(bOutArray);
    }

    //----------------------------------------------------
    public void sendTxt(String sTxt) {
        byte[] bOutArray = sTxt.getBytes();
        send(bOutArray);
    }

    //----------------------------------------------------
    private class ReadThread extends Thread {
        //private static final String STORAGE_SERVICE22 = "122133";

        @Override
        public void run() {
            super.run();
            while (true) {//!isInterrupted()
                Log.i("Read", "44444444444444444444");

                try {
                    if (mInputStream == null){
                        Log.i("Read", "22222--");
                        //App.getInstance().isSwitch = false;
                        return;
                    }

                    byte[] buffer = new byte[1024];
                    int size = mInputStream.read(buffer);
                    if (size > 6) {
                        ComBean ComRecData = new ComBean(sPort, buffer, size);

                        onDataReceived(ComRecData);
                    }
                    try {
                        Thread.sleep(50);//��ʱ50ms
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    //Log.i(STORAGE_SERVICE22, "66666666666666666666666");
                    return;
                }
            }
        }
    }

    // 判断奇数或偶数，位运算，最后一位是1则为奇数，为0是偶数
    static public int isOdd(int num) {
        return num & 0x1;
    }

    //转hex字符串转字节数组
    static public byte[] HexToByteArr(String inHex)//hex字符串转字节数组
    {
        int hexlen = inHex.length();
        byte[] result;
        if (isOdd(hexlen) == 1) {//奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {//偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = HexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    //-------------------------------------------------------
    static public byte HexToByte(String inHex)//Hex字符串转byte
    {
        return (byte) Integer.parseInt(inHex, 16);
    }

    //----------------------------------------------------
    private class SendThread extends Thread {
        public boolean suspendFlag = true;

        @Override
        public void run() {
            super.run();
            while (true) {
                doReadCardParm();

//                doSetParam();

                try {
                    Thread.sleep(iDelay);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

        }

        public byte[] communication(byte[] send) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            byte[] recv = null;
            int timeOut = 500;
            while (true) {
                if (timeOut <= 0)
                    break;
                timeOut--;
                try {
                    if (mInputStream.available() > 0) {
                        recv = receive();
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
            }
//        System.out.println("send:"+Convert.ByteArrToHex(send));
//        if(recv!=null)
//            System.out.println("recv:"+Convert.ByteArrToHex(recv));

            return recv;
        }

        private byte[] receive() {
            byte[] buffer = new byte[512];
            byte[] bRec = null;
            try {
                int size = mInputStream.read(buffer);
                bRec = new byte[size];
                for (int i = 0; i < size; i++) {
                    bRec[i] = buffer[i];
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bRec;
        }

        //�߳���ͣ
        public void setSuspendFlag() {
            this.suspendFlag = true;
        }

        //�����߳�
        public synchronized void setResume() {
            this.suspendFlag = false;
            notify();
        }
    }
  /*  byte[] Keys = new byte[6];
    Keys[0]=(byte)0xff;
    Keys[1]=(byte)0xff;
    Keys[2]=(byte)0xff;
    Keys[3]=(byte)0xff;
    Keys[4]=(byte)0xff;
    Keys[5]=(byte)0xff;*/

    public  void doSetParam() {

        byte[] btArray = new byte[22];//30
        btArray[0] = (byte) 0x5A;//5A
        btArray[1] = (byte) 0xAA;//AA
        btArray[2] = (byte) 15;//0x38 长度35
        btArray[3] = (byte) 0x03;//0x03 命令字

        btArray[4] = (byte) 0x25;//Tag(0x1025)
        btArray[5] = (byte) 0x10;//Tag(0x1025)
        btArray[6] = (byte) 0x01;//Len(0x0001)
        btArray[7] = (byte) 0x00;
        btArray[8] = (byte) 0x00;//Value（ 0-被动工作模式， 1 主动工作模式）主动返回 数据

        btArray[9] = (byte) 0x26;//Tag(0x1026)
        btArray[10] = (byte) 0x10;
        btArray[11] = (byte) 0x01;//Len(0x0001)
        btArray[12] = (byte) 0x00;
        btArray[13] = (byte) 0x00;//Value（ 0-串口通讯， 1-USB 通讯）



        btArray[14] = (byte) 0x27;//Tag(0x1027)
        btArray[15] = (byte) 0x10;//Tag(0x1027)
        btArray[16] = (byte) 0x01;//Len(0x0001)
        btArray[17] = (byte) 0x00;
        btArray[18] = (byte) 0x00;//Value（ 0-只读 ID， 1-读取 ID 和扇区内容）




        btArray[19] = (byte) -58; // CRC
        btArray[20] = (byte) 0x6B;//6B 包尾
        btArray[21] = (byte) 0xBB;//BB
        //
        //CRC效验
        Log.d("TTTT", "btArray.length" + btArray.length);
        int end = btArray.length - 4;
        Log.d("TTTT", "end" + end);
        byte[] arrCrc = subBytes(btArray, 2, end);
        int CRC = 0;
        for (int i = 0; i < arrCrc.length - 1; i++) {
            CRC ^= arrCrc[i];
        }
        CRC = ~CRC;//按位取反
        Log.d("TTTT", "发送CRC" + CRC);

        send(btArray);
    }
    /**
     * 读卡
     */
    private void doReadCardParm() {


        //读卡
        byte[] btArray = new byte[7];
        btArray[0] = (byte) 0x5A;//5A
        btArray[1] = (byte) 0xAA;//AA
        btArray[2] = (byte) 0x00;// 长度
        btArray[3] = (byte) 0x0E;//0x04 命令字

        btArray[4] = (byte) -15; // CRC
        btArray[5] = (byte) 0x6B;//6B 包尾
        btArray[6] = (byte) 0xBB;//BB
        //
        //CRC效验
        Log.d("TTTT", "btArray.length" + btArray.length);
        int end = btArray.length - 4;
        Log.d("TTTT", "doReadCardParm end=" + end);
        byte[] arrCrc = subBytes(btArray, 2, end);
        int CRC = 0;
        for (int i = 0; i < arrCrc.length - 1; i++) {
            CRC ^= arrCrc[i];
        }
        CRC = ~CRC;//按位取反
        Log.d("TTTT", "doReadCardParm CRC" + CRC);
        send(btArray);


        //扇区读
      /*  byte[] btArray = new byte[10];
        btArray[0] = (byte) 0x5A;//5A
        btArray[1] = (byte) 0xAA;//AA
        btArray[2] = (byte) 3;// 长度
        btArray[3] = (byte) 0x0B;//0x04 命令字

        btArray[4] = (byte) 0x4002;// 长度
        btArray[5] = (byte) 0x0001;//Value(扇区地址)
        btArray[6] = (byte) 8;//Value(扇区地址)

        btArray[7] = (byte) -4; // CRC
        btArray[8] = (byte) 0x6B;//6B 包尾
        btArray[9] = (byte) 0xBB;//BB
        //
        //CRC效验
        Log.d("TTTT", "btArray.length" + btArray.length);
        int end = btArray.length - 4;
        Log.d("TTTT", "end doGetParm()" + end);
        byte[] arrCrc = subBytes(btArray, 2, end);
        int CRC = 0;
        for (int i = 0; i < arrCrc.length - 1; i++) {
            CRC ^= arrCrc[i];
        }
        CRC = ~CRC;//按位取反
        Log.d("TTTT", "doGetParm() CRC" + CRC);
        send(btArray);*/

        // 获取参数
     /*   byte[] btArray = new byte[7];
        btArray[0] = (byte) 0x5A;//5A
        btArray[1] = (byte) 0xAA;//AA
        btArray[2] = (byte) 0x00;// 长度
        btArray[3] = (byte) 0x04;//0x04 命令字

        btArray[4] = (byte) -5; // CRC
        btArray[5] = (byte) 0x6B;//6B 包尾
        btArray[6] = (byte) 0xBB;//BB
        //
        //CRC效验
        Log.d("TTTT", "btArray.length" + btArray.length);
        int end = btArray.length - 4;
        Log.d("TTTT", "end doGetParm()" + end);
        byte[] arrCrc = subBytes(btArray, 2, end);
        int CRC = 0;
        for (int i = 0; i < arrCrc.length - 1; i++) {
            CRC ^= arrCrc[i];
        }
        CRC = ~CRC;//按位取反
        Log.d("TTTT", "doGetParm() CRC" + CRC);
        send(btArray);*/
    }

    /**
     * 从一个byte[]数组中截取一部分
     *
     * @param src
     * @param begin
     * @param count
     * @return
     */
    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        for (int i = begin; i < begin + count; i++)
            bs[i - begin] = src[i];
        return bs;
    }

    //----------------------------------------------------
    public int getBaudRate() {
        return iBaudRate;
    }

    public boolean setBaudRate(int iBaud) {
        if (_isOpen) {
            return false;
        } else {
            iBaudRate = iBaud;
            return true;
        }
    }

    public boolean setBaudRate(String sBaud) {
        int iBaud = Integer.parseInt(sBaud);
        return setBaudRate(iBaud);
    }

    //----------------------------------------------------
    public String getPort() {
        return sPort;
    }

    public boolean setPort(String sPort) {
        if (_isOpen) {
            return false;
        } else {
            this.sPort = sPort;
            return true;
        }
    }

    //----------------------------------------------------
    public boolean isOpen() {
        return _isOpen;
    }

    //----------------------------------------------------
    public byte[] getbLoopData() {
        return _bLoopData;
    }

    //----------------------------------------------------
    public void setbLoopData(byte[] bLoopData) {
        this._bLoopData = bLoopData;
    }

    //----------------------------------------------------
    public void setTxtLoopData(String sTxt) {
        this._bLoopData = sTxt.getBytes();
    }

    //----------------------------------------------------
    public void setHexLoopData(String sHex) {
        this._bLoopData = MyFunc.HexToByteArr(sHex);
    }

    //----------------------------------------------------
    public int getiDelay() {
        return iDelay;
    }

    //----------------------------------------------------
    public void setiDelay(int iDelay) {
        this.iDelay = iDelay;
    }

    //----------------------------------------------------
    public void startSend() {
        if (mSendThread != null) {
            mSendThread.setResume();
        }
    }

    //----------------------------------------------------
    public void stopSend() {
        if (mSendThread != null) {
            mSendThread.setSuspendFlag();
        }
    }

    //----------------------------------------------------
    protected abstract void onDataReceived(ComBean ComRecData);
}